package com.x.compute.common.handle;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.googlecode.aviator.lexer.token.OperatorType;
import com.x.compute.common.constant.StrConstant;
import com.x.compute.common.constant.VarTypeEnum;
import com.x.compute.common.entity.VarHandleResult;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.*;

/**
 * 数值变量处理
 * @author xuxin
 */
@Slf4j
public class NumberVarHandle implements VarTypeHandle {

    private static final String PERCENT_FORMAT = OperatorType.MULT.token + "0.01";

    private static final List<String> OPERATOR = Collections.unmodifiableList(Arrays.asList(
            OperatorType.ADD.token,
            StrConstant.OPERATOR_SUB,
            OperatorType.DIV.token,
            OperatorType.MULT.token));

    @Override
    public VarTypeEnum type() {
        return VarTypeEnum.NUMBER;
    }

    /**
     * 公式转换
     * @param expression
     * @return
     */
    @Override
    public String formatExpression(String expression){
        if (!expression.contains(OperatorType.MOD.token)){
            return expression;
        }
        String[] arr = expression.split(OperatorType.MOD.token);
        if (arr.length == 1){
            return arr[0] + PERCENT_FORMAT;
        }
        for (int i = 0; i < arr.length; i++) {
            if (i == arr.length - 1){
                break;
            }
            if (OPERATOR.contains(String.valueOf(arr[i+1].trim().charAt(0)))){
                arr[i] = arr[i] + PERCENT_FORMAT;
                continue;
            }
            arr[i] = arr[i] + OperatorType.MOD.token;
        }
        return String.join(StrUtil.EMPTY, arr);
    }

    @Override
    public VarHandleResult handle(Map<String, Object> fieldMap, String expression) {
        VarHandleResult result = VarHandleResult.builder().expression(expression).build();
        if (NumberUtil.isNumber(expression)){
            return result.setReturn(true).setResult(expression);
        }
        String percentValue = judgePercentReference(fieldMap, expression);
        if (percentValue != null){
            log.info("计算公式：{}，变量参数：{}", expression, JSONUtil.toJsonStr(fieldMap));
            return result.setReturn(true).setResult(percentValue);
        }
        //变量值格式转换（%）
        for (Map.Entry<String, Object> entry : fieldMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue().toString();
            boolean isContainPercent = value.contains(OperatorType.MOD.token);
            value = isContainPercent ? value.replace(OperatorType.MOD.token, StrUtil.EMPTY) : value;
            if (NumberUtil.isNumber(value)){
                BigDecimal decimalValue = isContainPercent ? new BigDecimal(value + PERCENT_FORMAT) : new BigDecimal(value);
                fieldMap.put(key,decimalValue);
            }
        }
        //表达式格式转换（%）
        expression = formatExpression(expression);
        return result.setExpression(expression);
    }

    /**
     * 判断是否为百分数引用
     * @param fieldMap
     * @param expression
     * @return
     */
    private static String judgePercentReference(Map<String, Object> fieldMap, String expression){
        if (!expression.contains(OperatorType.MOD.token)){
            return null;
        }
        Set<String> keys = fieldMap.keySet();
        if (keys.size() == 1){
            String key = keys.iterator().next();
            String value = fieldMap.get(key).toString();
            return key.equals(expression) && value.contains(OperatorType.MOD.token) ? value : null;
        }
        return null;
    }

}
